﻿using System.Linq;
using K9Nano.Dependency;
using Microsoft.Extensions.Logging;

namespace K9Nano.Events
{
    public class DefaultEventHandlerConventionRegister : IEventHandlerConventionRegister, ISingletonDependency
    {
        private readonly IEventBus _eventBus;
        private readonly IIocHelper _iocHelper;
        private readonly ILogger _logger;
        private readonly ITypeEventNameGenerator _typeEventNameGenerator;

        public DefaultEventHandlerConventionRegister(IEventBus eventBus, 
            IIocHelper iocHelper,
            ILogger<DefaultEventHandlerConventionRegister> logger,
            ITypeEventNameGenerator typeEventNameGenerator)
        {
            _iocHelper = iocHelper;
            _logger = logger;
            _typeEventNameGenerator = typeEventNameGenerator;
            _eventBus = eventBus;
        }

        public void RegisterHandlers()
        {
            var handlers = _iocHelper.GetRegisteredTypes<IEventHandler>();
            foreach (var handler in handlers)
            {
                var interfaceType = handler.GetInterfaces()
                    .FirstOrDefault(i => i.GetGenericTypeDefinition() == typeof(IEventHandler<>)
                                         || i.GetGenericTypeDefinition() == typeof(IAsyncEventHandler<>));
                if (interfaceType == null)
                {
                    _logger.LogError($"{handler} does implemented neither IEventHandler<> nor IAsyncEventHandler<> and will be ignored.");
                    continue;
                }

                var genericArgType = interfaceType.GenericTypeArguments[0];
                var eventName = _typeEventNameGenerator.Generate(genericArgType);
                _eventBus.Register(eventName, handler);
                _logger.LogDebug($"Registered {handler} for {eventName}");
            }
        }
    }
}